package es.udima.geo.geoserver.persistence;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import es.udima.geo.geoserver.entities.User;

/**
 * DAO encargado del enlace de la persistencia relativa a los usuarios.
 * 
 * @author david
 * 
 */
public class UserDAO extends GenericDAO {

    /**
     * Constructor
     */
    public UserDAO() {
    }

    /**
     * <p>
     * Crea un nuevo usuario en el sistema.
     * </p>
     * 
     * @param user
     *            Usuario que va a ser creado.
     */
    public void createUser(User user) {
	EntityManager em = createEntityManager();
	EntityTransaction et = em.getTransaction();
	et.begin();
	em.persist(user);
	et.commit();
	em.close();
    }

    /**
     * <p>
     * Actualiza los datos del usuario.
     * </p>
     * 
     * @param user
     *            Usuario que va a ser modificado.
     */
    public void updateUser(User user) {
	EntityManager em = createEntityManager();
	EntityTransaction et = em.getTransaction();
	et.begin();
	em.merge(user);
	et.commit();
	em.close();
    }

    /**
     * <p>
     * Recupera de base de datos los usuarios activos.
     * </p>
     * <p>
     * Se entiende como usuarios activos aquellos que no han sido marcados en la
     * tabla de usuarios como inactivos.
     * </p>
     * 
     * @return Lista de usuarios activos.
     */
    public List<User> retrieveActiveUsers() {
	EntityManager em = createEntityManager();

	CriteriaBuilder cb = em.getCriteriaBuilder();
	CriteriaQuery<User> cq = cb.createQuery(User.class);
	Root<User> r = cq.from(User.class);
	cq.select(r);
	cq.where(cb.equal(r.get("active"), 1));
	TypedQuery<User> tq = em.createQuery(cq);
	return tq.getResultList();
    }

    /**
     * <p>
     * Recupera de base de datos el usuario con el id de usuario el pasado como
     * parámetro.
     * </p>
     * 
     * @param userId
     *            Identificador de usuario por el que se trata de recuperar un
     *            usuario.
     * @return Usuario leído o null si no existía un usuario con el id de
     *         usuario pasado como parámetro.
     */
    public User retrieveUserByUserId(String userId) {
	EntityManager em = createEntityManager();
	User u = em.find(User.class, userId);
	return u;
    }

    /**
     * <p>
     * Recupera de base de datos el usuario con el nombre de usuario el pasado
     * como parámetro.
     * </p>
     * 
     * @param userName
     *            Nombre de usuario por el que se trata de recuperar un usuario.
     * @return Usuario leído o null si no existía un usuario con el nombre de
     *         usuario pasado como parámetro.
     */
    public User retrieveUserByUserName(String userName) {
	EntityManager em = createEntityManager();

	CriteriaBuilder cb = em.getCriteriaBuilder();
	CriteriaQuery<User> cq = cb.createQuery(User.class);
	Root<User> r = cq.from(User.class);
	cq.select(r);
	cq.where(cb.equal(r.get("userName"), userName));
	TypedQuery<User> tq = em.createQuery(cq);

	User res = null;
	List<User> dataRead = tq.getResultList();
	if (!dataRead.isEmpty()) {
	    res = dataRead.get(0);
	}

	return res;
    }
}
